import store from '../../redux/store.js';
import {setUserAction} from '../../redux/actions/user_action'

import axios from 'axios';
import QueryString from "qs";

import { BASE_URL, TIME_OUT} from './config.js'
import {message} from 'antd'

const pendingMap = new Map();

const LoadingInstance = {
  _target: null,
  _count: 0
};


function myAxios(axiosConfig, customOptions, loadingOptions=false) {
  if (axiosConfig.data && axiosConfig.method==='get'){
    axiosConfig.url = 
      axiosConfig.url + '?' + encodeURI(QueryString.stringify(axiosConfig.data))
  }
  const isToken = axiosConfig.isToken
  axiosConfig.headers={
    'Content-Type': 'application/x-www-form-urlencoded'
  }
  const service = axios.create({
    baseURL: BASE_URL, // 设置统一的请求前缀
    timeout: TIME_OUT, // 设置统一的超时时长
  });

  // 自定义配置
  let custom_options = Object.assign({
    repeat_request_cancel: true, // 是否开启取消重复请求, 默认为 true
    loading: false, // 是否开启loading层效果, 默认为false
    reduct_data_format: true, // 是否开启简洁的数据结构响应, 默认为true
    error_message_show: true, // 是否开启接口错误信息展示,默认为true
    code_message_show: false, // 是否开启code不为0时的信息提示, 默认为false
  }, customOptions);

  // 请求拦截
  service.interceptors.request.use(
    config => {
      removePending(config);
      custom_options.repeat_request_cancel && addPending(config); 
      // 创建loading实例
    //   if (custom_options.loading) {
    //     LoadingInstance._count++;
    //     if(LoadingInstance._count === 1) {
    //       LoadingInstance._target = ElLoading.service(loadingOptions);
    //     }
    //   }
      // 自动携带token
      if (typeof window !== "undefined" && isToken) {
        const token = localStorage.getItem('token')
        token && (config.headers['token'] = `zzl_${token}`)
      }

      return config;
    }, 
    error => {
      return Promise.reject(error);
    }
  );

  // 响应拦截
  service.interceptors.response.use(
    response => {
      removePending(response.config);
      custom_options.loading && closeLoading(custom_options); // 关闭loading

      if(custom_options.code_message_show && response.data && response.data.code !== 0) {

        message.error(response.data.message)
        return Promise.reject(response.data); // code不等于0, 页面具体逻辑就不执行了
      }

      return custom_options.reduct_data_format ? response.data : response;
    },
    error => {
      error.config && removePending(error.config);
      custom_options.loading && closeLoading(custom_options); // 关闭loading
      custom_options.error_message_show && httpErrorStatusHandle(error); // 处理错误状态码
      return Promise.reject(error); // 错误继续返回给到具体页面
    }
  );

  return service(axiosConfig)
}

export default myAxios;

/**
 * 处理异常
 * @param {*} error 
 */
function httpErrorStatusHandle(error) {
  // 处理被取消的请求
  if(axios.isCancel(error)) return console.error('请求的重复请求：' + error.message);
  let messageInfo = '';
  if (error && error.response) {
    switch(error.response.status) {
      case 302: messageInfo = '接口重定向了！';break;
      case 400: messageInfo = '参数不正确！';break;
      case 401: 
      messageInfo = '您未登录，或者登录已经超时，请先登录！';
        store.dispatch(setUserAction({}))
        break;
      case 403: messageInfo = '您没有权限操作！'; break;
      case 404: messageInfo = `请求地址出错: ${error.response.config.url}`; break; // 在正确域名下
      case 408: messageInfo = '请求超时！'; break;
      case 409: messageInfo = '系统已存在相同数据！'; break;
      case 500: messageInfo = '服务器内部错误！'; break;
      case 501: messageInfo = '服务未实现！'; break;
      case 502: messageInfo = '网关错误！'; break;
      case 503: messageInfo = '服务不可用！'; break;
      case 504: messageInfo = '服务暂时无法访问，请稍后再试！'; break;
      case 505: messageInfo = 'HTTP版本不受支持！'; break;
      default: messageInfo = '异常问题，请联系管理员！'; break
    }
  }
  if (error.message.includes('timeout')) messageInfo = '网络请求超时！';
  if (error.message.includes('Network')) messageInfo = window.navigator.onLine ? '服务端异常！' : '您断网了！';
console.info(messageInfo)
message.error(messageInfo)
}

/**
 * 关闭Loading层实例
 * @param {*} _options 
 */
function closeLoading(_options) {
  if(_options.loading && LoadingInstance._count > 0) LoadingInstance._count--;
  if(LoadingInstance._count === 0) {
    LoadingInstance._target.close();
    LoadingInstance._target = null;
  }
}

/**
 * 储存每个请求的唯一cancel回调, 以此为标识
 * @param {*} config 
 */
function addPending(config) {
  const pendingKey = getPendingKey(config);
  config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => {
    if (!pendingMap.has(pendingKey)) {
      pendingMap.set(pendingKey, cancel);
    }
  });
}

/**
 * 删除重复的请求
 * @param {*} config 
 */
function removePending(config) {
  // const pendingKey = getPendingKey(config);
  // if (pendingMap.has(pendingKey)) {
  //    const cancelToken = pendingMap.get(pendingKey);
  //    // 如你不明白此处为什么需要传递pendingKey可以看文章下方的补丁解释
  //    cancelToken(pendingKey);
  //    pendingMap.delete(pendingKey);
  // }
}

/**
 * 生成唯一的每个请求的唯一key
 * @param {*} config 
 * @returns 
 */
function getPendingKey(config) {
  let {url, method, params, data} = config;
  // if(typeof data === 'string') data = JSON.parse(data); // response里面返回的config.data是个字符串对象
  // return [url, method, JSON.stringify(params), JSON.stringify(data)].join('&');
  if(typeof data !== 'string') data=JSON.stringify(data)
  return [url, method, JSON.stringify(params), data].join('&');
}